#include "utils.h"

char **splitFunc(const char *cmd, int *tokensSize)
{
    char *delimiters = " \t\n";
    return splitString(cmd, delimiters, tokensSize);
}

char **splitString(const char *str, const char *delimiters, int *tokensSize)
{
    // 拷贝一份cmd，避免对传输参数进行修改
    char *strCopy = strdup(str);
    if (!strCopy)
    {
        perror("strdup");
        return NULL;
    }

    // TODO: 去除cmd首尾的空字符
    *tokensSize = 0;
    // 第一轮调用strtok，获取字符数组长度
    char *temp = strCopy;
    char *token = strtok(temp, delimiters);
    while (token)
    {
        token = strtok(NULL, delimiters);
        (*tokensSize)++;
    }

    // 为字符串数组分配空间
    char **tokens = (char **)malloc((*tokensSize) * sizeof(char *));
    if (!tokens)
    {
        perror("malloc");
        free(strCopy);
        exit(EXIT_FAILURE);
    }

    // 第二轮调用strtok，存储分割后的字符串
    strcpy(strCopy, str);
    temp = strCopy;
    token = strtok(temp, delimiters);
    for (int i = 0; i < *tokensSize; i++)
    {
        tokens[i] = strdup(token);
        if (!tokens[i])
        {
            perror("strdup");
            for (int j = 0; j < i; j++)
            {
                free(tokens[j]);
            }
            free(tokens);
            free(strCopy);
            return NULL;
        }
        token = strtok(NULL, delimiters);
    }

    free(strCopy);

    return tokens;
}

// void freeArray(void **array, int size) {
void freeArrayOfPtrs(void **ptrToArray, int arraySize)
{
    if (ptrToArray == NULL || *ptrToArray == NULL)
        return;

    for (int i = 0; i < arraySize; i++)
    {
        if (ptrToArray[i] != NULL)
        {
            free(ptrToArray[i]);
            ptrToArray[i] = NULL; // Notify that the memory has been freed
        }
    }
    free(ptrToArray);
    ptrToArray = NULL; // Notify that the ptrToArray memory has been freed
}

void freeTokens(char ***tokens, int tokensSize)
{
    if (NULL == tokens || NULL == *tokens)
        return;

    for (int j = 0; j < tokensSize; j++)
    {
        free((*tokens)[j]);
    }
    free(*tokens);

    *tokens = NULL;
}

/*
 * 单元测试函数实现，测试完成后需要删除
 * 创建人：曾爽
 * 创建时间：2024/07/06
 * */

void unitest_splitFunc(void)
{
    char *cmd = "cd /home/tsang/";
    int size = 0;

    char **tokens = splitFunc(cmd, &size);

    // printf("Tokens size = %d\n", size);
    // printf("Tokens:\n");
    if (size > 0)
    {
        for (int i = 0; i < size; i++)
        {
            printf("'%s'\n", tokens[i]);
        }
        freeTokens(&tokens, size);
    }
    else
    {
        printf("error\n");
    }
}

void unitest_splitString(void)
{
    char *cmd = "cd /home/tsang/";
    char *delimeter = " \t\n/";
    int size = 0;

    char **tokens = splitString(cmd, delimeter, &size);

    printf("Tokens size = %d\n", size);
    printf("Tokens:\n");
    if (size > 0)
    {
        for (int i = 0; i < size; i++)
        {
            printf("'%s'\n", tokens[i]);
        }
        // freeTokens(&tokens, size);
        freeArrayOfPtrs((void **)tokens, size);
        if (tokens == NULL)
        {
            printf("清理成功\n");
        }
        else
        {
            // printf("清理失败\n");
        }
    }
    else
    {
        printf("error\n");
    }
}

void trimString(char *str)
{
    int start, end, len;

    len = strlen(str);

    // 找到第一个非空格字符的位置
    for (start = 0; start < len; start++)
    {
        if (!isspace(str[start]))
        {
            break;
        }
    }

    // 找到最后一个非空格字符的位置
    for (end = len - 1; end >= 0; end--)
    {
        if (!isspace(str[end]))
        {
            break;
        }
    }

    // 如果start超过了end，说明字符串全是空格
    if (start > end)
    {
        str[0] = '\0'; // 将字符串置为空字符串
    }
    else
    {
        // 将有效的字符复制到字符串开头
        memmove(str, str + start, end - start + 1);
        str[end - start + 1] = '\0'; // 添加字符串结尾的空字符
    }
}

bool getServerAbsPath(splictDataCarrier_st *splictDataCarrier, char *serverAbsPath)
{
    // 字符串拆分【客户端传来的命令】
    char command[255] = {0};
    memcpy(command, splictDataCarrier->command, strlen(splictDataCarrier->command));
    // printf("splictDataCarrier,username:%s\n",splictDataCarrier->username);
    // 删除字符串前后的空格
    trimString(command);
    // 判断路径是否存在【使用一次strtok得到分割符前的一个字符串】
    // 第一个空格得到的是命令
    char *token = strtok(command, " "); // 通过空格拆分字符串
    trimString(token);
    if (strcmp(token, "ls") != 0)
    {
        // 第二个空格得到的是参数 mkdir a/b/c
        token = strtok(NULL, " ");
        // 删除第二个参数前后的空格
        trimString(token);
    }
    if (strcmp(token, "ls") == 0) token = "";
    // 判断用户穿过来的路径是绝对地址还是相对地址
    // 如果是绝对地址，那么第一个字符一定是 /
    char absPath[1024] = {0};
    char tmpClientPath[255] = {0};
    // printf("commond:%s\n", command);
    // printf("splictDataCarrier->username:%s\n", splictDataCarrier->username);
    // printf("splictDataCarrier->virtual_path:%s\n", splictDataCarrier->virtual_path);
    // printf("splictDataCarrier->serverPath:%s\n", splictDataCarrier->serverPath);
    if (token[0] == '/')
    {
        // 拼接绝对地址【服务器工作路径 + 客户端用户名 + 传过来的绝对路径】
        // printf("splictDataCarrier->serverPath:%s\n", splictDataCarrier->serverPath);
        // printf("splictDataCarrier->username:%s\n", splictDataCarrier->username);

        sprintf(absPath, "%s/%s%s", splictDataCarrier->serverPath, splictDataCarrier->username, token);
        sprintf(tmpClientPath, "%s", token);
        // printf("绝对路径:%s\n", absPath);
    }
    else
    {
        // 拼接相对路径 【服务器工作路径 + 客户端用户名 + 客户端当前路径 + 传过来的相对路径】
        // printf("splictDataCarrier->username:%s\n", splictDataCarrier->username);
        // printf("splictDataCarrier->virtual_path:%s\n", splictDataCarrier->virtual_path);
        // printf("splictDataCarrier->serverPath:%s\n", splictDataCarrier->serverPath);
        // printf("splictDataCarrier->virtual_path:%s\n", splictDataCarrier->virtual_path);
        sprintf(absPath, "%s/%s%s/%s", splictDataCarrier->serverPath, splictDataCarrier->username, splictDataCarrier->virtual_path, token);
        sprintf(tmpClientPath, "%s%s", splictDataCarrier->virtual_path, token);
        
    }
    // return;
    // 获取文件相关的信息
    memcpy(serverAbsPath,absPath,strlen(absPath));
    struct stat statbuf;
    memcpy(serverAbsPath, absPath, strlen(absPath));
    int ret = stat(absPath, &statbuf);
    if (ret == 0)
    {
        return true;
    }

    return false;
}
